package com.snow.jpa;

import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.snow.exception.CommonRuntimeException;
import com.snow.jpa.model.IBasePageParams;
import com.snow.jpa.model.IBaseSearchParams;
import com.snow.service.IAuthComponent;
import com.snow.view.PageData;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;

import javax.transaction.Transactional;
import java.util.List;
import java.util.Optional;

/**
 * 增删改查业务
 *
 * @author by 13119
 */
@Getter
@Slf4j
public abstract class BaseService<R extends BaseRepository<E, ID>, E extends IBaseEntity<ID>, ID> {

    protected R repository;

    public BaseService(R repository) {
        this.repository = repository;
    }

    /**
     * 保存
     */
    @Transactional(rollbackOn = Exception.class)
    public E save(E e) {
        IAuthComponent authComponent = SpringUtil.getBean(IAuthComponent.class);
        if (e instanceof ITenantEntity) {
            if (((ITenantEntity) e).getTenantId() == null) {
                ((ITenantEntity) e).setTenantId(authComponent.getCurrentUser().getTenantId());
            }
        }
        if (e instanceof ICreateInfoEntity) {
            if (((ICreateInfoEntity) e).getCreateId() == null) {
                ((ICreateInfoEntity) e).setCreateInfo(authComponent.getCurrentUser());
            }
        }
        if (e instanceof IDeletedEntity) {
            ((IDeletedEntity) e).setDeleted(false);
        }
        return this.repository.save(e);
    }

    @Transactional(rollbackOn = Exception.class)
    public E create(E e) {
        IAuthComponent authComponent = SpringUtil.getBean(IAuthComponent.class);
        if (e instanceof ITenantEntity) {
            if (((ITenantEntity) e).getTenantId() == null) {
                ((ITenantEntity) e).setTenantId(authComponent.getCurrentUser().getTenantId());
            }
        }
        if (e instanceof ICreateInfoEntity) {
            if (((ICreateInfoEntity) e).getCreateId() == null) {
                ((ICreateInfoEntity) e).setCreateInfo(authComponent.getCurrentUser());
            }
        }
        if (e instanceof IDeletedEntity) {
            ((IDeletedEntity) e).setDeleted(false);
        }
        return this.repository.save(e);
    }

    public List<E> saveAll(List<E> eList) {
        IAuthComponent authComponent = SpringUtil.getBean(IAuthComponent.class);
        for (E e : eList) {
            if (e instanceof ITenantEntity) {
                if (((ITenantEntity) e).getTenantId() == null) {
                    ((ITenantEntity) e).setTenantId(authComponent.getCurrentUser().getTenantId());
                }
            }
            if (e instanceof ICreateInfoEntity) {
                if (((ICreateInfoEntity) e).getCreateId() == null) {
                    ((ICreateInfoEntity) e).setCreateInfo(authComponent.getCurrentUser());
                }
            }
            if (e instanceof IDeletedEntity) {
                if (((IDeletedEntity) e).getDeleted() == null) {
                    ((IDeletedEntity) e).setDeleted(false);
                }
            }
        }
        return this.repository.saveAll(eList);
    }

    @Transactional(rollbackOn = Exception.class)
    public E update(E e) {
        if (StrUtil.isBlankIfStr(e.getId())) {
            throw new CommonRuntimeException("更新主键不能为空");
        }
        return this.repository.save(e);
    }

    /**
     * 删除
     */
    @Transactional(rollbackOn = Exception.class)
    public E delete(ID id) {
        Optional<E> obj = repository.findById(id);
        if (obj.isPresent()) {
            if (obj.get() instanceof IDeletedEntity) {
                ((IDeletedEntity) obj.get()).setDeleted(true);
                repository.save(obj.get());
            } else {
                repository.deleteById(id);
            }
            return obj.get();
        }
        throw new CommonRuntimeException("数据记录不存在,请刷新重试");
    }

    /**
     * 普通查询
     */
    @Transactional(rollbackOn = Exception.class)
    public List<E> search(IBaseSearchParams params) {
        if (params == null) {
            return repository.lambdaQuery().findAll();
        }
        return repository.findAll(repository.toSpec(params));
    }

    @Transactional(rollbackOn = Exception.class)
    public LambdaQueryBuilder<E, ID> lambdaQuery() {
        return repository.lambdaQuery();
    }

    public E findBy(String column, Object value) {
        return repository.findBy(column, value);
    }

    public List<E> findAllIn(String column, Object... value) {
        return repository.lambdaQuery().in(column, value).findAll();
    }

    public List<E> findAllBy(String column, Object value) {
        return repository.findAllBy(column, value);
    }

    public List<E> findAllBy(String column, Object value, boolean enableTenantFilter) {
        return repository.findAllBy(column, value, enableTenantFilter);
    }

    /**
     * 分页查询
     */
    @Transactional(rollbackOn = Exception.class)
    public PageData<E> page(IBasePageParams params) {
        return repository.page(params);
    }

    public E get(ID id) {
        return repository.findById(id).orElse(null);
    }

    public BaseService<R, E, ID> disTenantFilter() {
        LambdaQueryBuilder.disableTenantFilter();
        return this;
    }

}
